﻿#pragma once


#include <queue>
#include <bitset>
#include <optional>

namespace Base {

	class KeyboardEvent {
	public:
		enum class Type
		{
			Press,
			Release
		};

	private:
		Type type;
		unsigned char code;
	public:
		KeyboardEvent(Type type, unsigned char code) :
			type(type),
			code(code) {}

		bool IsPressed()const {
			return type == Type::Press;
		}

		bool IsReleased()const {
			return type == Type::Release;
		}
		unsigned char GetCode() const {
			return code;
		}
	};


	//  键盘
	class Keyboard
	{
	public:

		// key event
		bool KeyIsPressed(unsigned char keycode)const;
		std::optional<KeyboardEvent> ReadKey();
		bool KeyIsEmpty() const;
		void FlushKey();

		// char event
		std::optional<char> ReadChar();
		bool CharIsEmpty() const;
		void FlushChar();
		void Flush();


		// win32 callback
		void OnKeyPresed(unsigned char keycode);
		void OnKeyReleased(unsigned char keycode);
		void OnChar(char ch);
		void ClearState();

	private:

		void TrimCharBuffer();
		void TrimKeyBuffer();

	private:
		static constexpr unsigned int kKeys = 256;
		static constexpr unsigned int kBufferSize = 16;

		std::bitset<kKeys> m_keyStates;
		std::queue<KeyboardEvent> m_keyEventBuffer;
		std::queue<char> m_charBuffer;

	};

}
